Skip to content

feat(partitions): add consensus per partition and extra#3071

Open
numinnex wants to merge 7 commits intomasterfrom
store_consumer_offset
Open

feat(partitions): add consensus per partition and extra#3071
numinnex wants to merge 7 commits intomasterfrom
store_consumer_offset

Conversation

@numinnex
Copy link
Copy Markdown
Contributor

@numinnex numinnex commented Apr 2, 2026

Implement StoreConsumerOffset and DeleteConsumerOffset as replicated operations on partition. Additionally move partitions to an consensus per partition model, rather than relying on one instance of consensus for all of the partitions.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 0.42265% with 1178 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.23%. Comparing base (051475a) to head (b029988).

Files with missing lines Patch % Lines
core/partitions/src/iggy_partition.rs 0.00% 859 Missing ⚠️
core/consensus/src/observability.rs 0.00% 122 Missing ⚠️
core/shard/src/lib.rs 0.00% 80 Missing ⚠️
core/partitions/src/types.rs 0.00% 37 Missing ⚠️
core/partitions/src/offset_storage.rs 0.00% 33 Missing ⚠️
core/partitions/src/iggy_partitions.rs 0.00% 27 Missing ⚠️
core/simulator/src/client.rs 0.00% 11 Missing ⚠️
core/simulator/src/replica.rs 0.00% 9 Missing ⚠️

❌ Your patch check has failed because the patch coverage (0.42%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3071      +/-   ##
============================================
- Coverage     70.52%   70.23%   -0.29%     
  Complexity      943      943              
============================================
  Files          1115     1115              
  Lines         95388    95274     -114     
  Branches      72589    72490      -99     
============================================
- Hits          67275    66920     -355     
- Misses        25634    25859     +225     
- Partials       2479     2495      +16     
Components Coverage Δ
Rust Core 70.21% <0.42%> (-0.35%) ⬇️
Java SDK 62.30% <ø> (ø)
C# SDK 69.10% <ø> (-0.31%) ⬇️
Python SDK 81.43% <ø> (ø)
Node SDK 91.31% <ø> (-0.10%) ⬇️
Go SDK 38.97% <ø> (ø)
Files with missing lines Coverage Δ
core/binary_protocol/src/consensus/operation.rs 94.36% <100.00%> (+0.16%) ⬆️
core/binary_protocol/src/dispatch.rs 90.99% <100.00%> (+0.08%) ⬆️
core/partitions/src/lib.rs 0.00% <ø> (ø)
core/shard/src/router.rs 0.00% <ø> (ø)
core/simulator/src/replica.rs 0.00% <0.00%> (ø)
core/simulator/src/client.rs 0.00% <0.00%> (ø)
core/partitions/src/iggy_partitions.rs 0.00% <0.00%> (ø)
core/partitions/src/offset_storage.rs 0.00% <0.00%> (ø)
core/partitions/src/types.rs 0.00% <0.00%> (ø)
core/shard/src/lib.rs 0.00% <0.00%> (ø)
... and 2 more

... and 25 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

offset: u64,
) -> Result<(), IggyError> {
let pending = PendingConsumerOffsetCommit::upsert(kind, consumer_id, offset);
self.persist_consumer_offset_commit(pending).await?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consumer offsets are persisted to disk here during the prepare phase (before quorum), unlike SendMessages which only writes to the in-memory journal during prepare and persists to disk during commit (commit_messages).

if the prepare never commits (leader crash, view change), disk has uncommitted values with no rollback mechanism. on restart, the uncommitted offset file is loaded as if it were committed.

recommended fix: move the persist_consumer_offset_commit call from persist_and_stage_* (prepare phase) to commit_consumer_offset_entry (commit phase). during prepare, only stage in-memory. this eliminates the rollback problem entirely and aligns with the SendMessages pattern.

Copy link
Copy Markdown
Contributor Author

@numinnex numinnex Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the behavior of treating written offset as committed by default is fine, as in scenario where we restart a replica after crash we perform state transfer, which would overwrite the currently commited offset for that particular consumer.

let last_offset =
last_matching_offset.expect("non-empty poll result must have a last offset");
if let Err(err) = self.store_consumer_offset(consumer, last_offset) {
if let Err(err) = self
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poll_messages with auto_commit=true calls store_consumer_offset_and_persist which persists and applies directly without going through consensus replication. this creates three divergent write paths for consumer offsets:

  1. replicated via StoreConsumerOffset operation (new in this PR) - full prepare/commit cycle
  2. local-only persist + apply via auto-commit here - no replication
  3. in-memory-only via Partition::store_consumer_offset trait method (line 473) - no persistence, no replication

on failover, the new leader has no record of auto-committed offsets since they were never replicated. this is a pre-existing pattern, but now inconsistent since explicit StoreConsumerOffset IS replicated. worth documenting whether this is intentional (local optimization for consumer progress) or should be migrated to the consensus path.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for auto commit polls, at the end of the command_handler construct new Message<Prepare>, with StoreConsumerOffset command and run it through the on_message handler, the same way an StoreConsumerOffset client request would.

Additionally I think we should expand the StoreConsumerOffset command to allow for different levels of consistency such as no_ack or quorum, something that kafka does for SendMessages. This way the auto_commit from PollMessages command, could inherit that aswell.

@numinnex numinnex changed the title feat(partitions): implement StoreConsumerOffset and DeleteConsumerOffset feat(partitions): add consensus per partition and extra Apr 8, 2026
@numinnex numinnex requested a review from hubcio April 8, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants